﻿/**
 * @file ut_vector2.h
 * @author 杜涛（贺亚猛整理）
 * @brief 二维向量实现
 * @version 0.1
 * @date 2022-01-19
 * @copyright Copyright 2022 Langge Software Co., Ltd. All rights reserved.
 */
#ifndef UT_VECTOR_2_H
#define UT_VECTOR_2_H

#include "ut_symbols.h"
#include "ut_math.h"

BEGIN_SPACE_LANGE_VDR

/**
 * @brief 二维向量实现类，负责封装并实现二维向量
 *        各种操作
 * @tparam T - 存储向量元素类型
 */
template<typename T>
class UT_API UTVector2 
{
public:
    /**
     * @brief 构造函数
     */
    UTVector2()
        :m_tX(NAN)
        ,m_tY(NAN)
    {
    }
    /**
     * @brief 构造函数
     * @param x  - x元素
     * @param y  - y元素
     */
    UTVector2(const T &x,const T &y)
        :m_tX(x)
        ,m_tY(y)
    {
    }
    /**
     * @brief 构造函数
     * @param v - 向量元素数组
     */
    UTVector2(T v[2])
        :m_tX(v[0])
        ,m_tY(v[1])
    {
    }
    /**
     * @brief 析构函数 
     */
    ~UTVector2()
    {
    }
public:
    /**
     * @brief 设置向量x元素
     * @param x - 元素值 
     */
    void SetX(const T x)
    {
        m_tX = x;
    }
    /**
     * @brief 获取向量x元素
     * @return 返回向量x元素
     */
    T GetX() const
    {
        return m_tX;
    }
    /**
     * @brief 设置向量y元素
     * @param y - 元素值 
     */
    void SetY(const T y)
    {
        m_tY = y;
    }
    /**
     * @brief 获取向量y元素
     * @return 返回向量y元素
     */
    T GetY() const
    {
        return m_tY;
    }
    /**
     * @brief 检测当前向量是否无效
     * @return true   -   当前向量无效
     * @return false  -   当前向量有效
     */
    bool Invalid() const 
    { 
        return UTMath::IsNan(m_tX)||UTMath::IsNan(m_tY); 
    }
    /**
     * @brief 计算当前向量长度
     * @return 返回计算的当前向量长度
     */
    T Length() const
    {
        return (T)sqrt(m_tX*m_tX+m_tY*m_tY);
    }
    T Length2() const
    {
        return (T)(m_tX*m_tX+m_tY*m_tY);
    }
    /**
     * @brief 将当前向量归一化
     * @return 返回归一化之前的向量长度
     */
    T Normalize()
    {
        T len = Length();
        if (len>0.0) 
        {
            T val = 1.0f/len;
            m_tX *= val;
            m_tY *= val;
        }
        return len;
    }
public:
    /**
     * @brief 重载==操作符，用于检测两个向量是否相同
     * @param  vec   - 输入二维向量
     * @return true  - 如果两个二维向量相同
     * @return false - 如果两个二维向量不同
     */
    bool operator==(const UTVector2 &vec) const 
    { 
        return (0==UTMath::Compare(m_tX,vec.m_tX)&&
            0==UTMath::Compare(m_tY,vec.m_tY))?true:false; 
    }
    /**
     * @brief  重载!=操作符，用于检测两个向量是否不同
     * @param  vec    - 输入二维向量
     * @return true   - 如果两个向量不同
     * @return false  - 如果两个向量相同
     */
    bool operator!=(const UTVector2 &vec) const
    { 
        return (0!=UTMath::Compare(m_tX,vec.m_tX)&&
            0!=UTMath::Compare(m_tY,vec.m_tY))?true:false; 
    }
    /**
     * @brief  重载<操作符，用于比较两个向量大小
     * @param  vec   - 目标二维向量 
     * @return true  - 如果当前向量小于目标向量
     * @return false - 如果当前向量不小于目标向量
     */
    bool operator<(const UTVector2 &vec) const 
    {
        if(UTMath::Compare(m_tX,vec.m_tX)<0)
        {
            return true;
        }
        else if(UTMath::Compare(m_tX,vec.m_tX)>0)
        {
            return false;
        }
        else
        {  
            return UTMath::Compare(m_tY,vec.m_tY)<0?true:false;
        }
    }
    /**
     * @brief 重载-操作符，用于实现正负取反功能
     * @return 返回取反后的向量
     */
    UTVector2 operator-() const 
    {
        return UTVector2(-m_tX,-m_tY);
    }
    /**
     * @brief 重载+运算操作符，用于实现向量的加法
     * @param val - 加数
     * @return 返回加法运算后的向量
     */
    UTVector2 operator+(T val) const 
    {
        return UTVector2(m_tX+val,m_tY+val);
    }
    /**
     * @brief 重载+=操作符，用于实现向量自加
     * @param val - 加数
     * @return 返回自加后的自身引用 
     */
    UTVector2 &operator+=(T val)
    {
        m_tX+=val;
        m_tY+=val;
        return *this;
    }
    /**
     * @brief 重载-操作符,用于实现向量减法
     * @param val - 减数
     * @return 返回相减运算后的结果向量 
     */
    UTVector2 operator-(T val) const 
    {
        return UTVector2(m_tX-val,m_tY-val);
    }
    /**
     * @brief 重载-=操作符，用于实现向量自减
     * @param val - 减数
     * @return 返回自减后的自身引用 
     */
    UTVector2 &operator-=(T val) 
    {
        m_tX-=val;
        m_tY-=val;
        return *this;
    }
    /**
     * @brief 重载*操作符，用于实现向量乘法
     * @param val - 乘数
     * @return 返回相乘后的结果向量
     */
    UTVector2 operator*(T val) const 
    {
        return UTVector2(m_tX*val,m_tY*val);
    }
    /**
     * @brief 重载*=操作符，用于实现向量自乘
     * @param val - 乘数
     * @return  返回自身引用 
     */
    UTVector2 &operator*=(T val)
    {
        m_tX*=val;
        m_tY*=val;
        return *this;
    }
    /**
     * @brief 重载/操作符，用于实现向量除法
     * @param val - 除数
     * @return 返回除法运算后的结果向量 
     */
    UTVector2 operator/(T val) const 
    {
        return UTVector2(m_tX/val,m_tY/val);
    }
    /**
     * @brief 重载/=操作符，用于实现向量自除
     * @param val - 除数
     * @return 返回自身引用 
     */
    UTVector2 &operator/=(T val)
    {
        m_tX/=val;
        m_tY/=val;
        return *this;
    }
    /**
     * @brief 重载+操作符，用于实现两个向量之间的加法
     * @param vec - 加数
     * @return 返回加法运算后的结果向量
     */
    UTVector2 operator+(const UTVector2 &vec) const
    {
        return UTVector2(m_tX+vec.m_tX,m_tY+vec.m_tY);
    }
    /**
     * @brief 重载+=操作符，用于实现向量自加
     * @param vec - 加数
     * @return 返回自身引用
     */
    UTVector2 &operator+=(const UTVector2 &vec)
    {
        m_tX+=vec.m_tX;
        m_tY+=vec.m_tY;
        return *this;
    }
    /**
     * @brief 重载-操作符，用于实现向量减法
     * @param vec - 减数
     * @return 返回相减后的结果向量 
     */
    UTVector2 operator-(const UTVector2 &vec) const
    {
        return UTVector2(m_tX-vec.m_tX,m_tY-vec.m_tY);
    }
    /**
     * @brief 重载-=操作符，用于实现向量自减
     * @param vec - 减数
     * @return 返回自身引用
     */
    UTVector2 &operator-=(const UTVector2 &vec)
    {
        m_tX-=vec.m_tX;
        m_tY-=vec.m_tY;
        return *this;
    }
    /**
     * @brief 重载^操作符，实现向量叉乘
     * @param vec - 乘数
     * @return 返回叉乘结果 
     */
    T operator^(const UTVector2& vec) const
    {
        return m_tX*vec.m_tY-m_tY*vec.m_tX;
    }
    /**
     * @brief  重载*操作符，实现向量点积
     * @param  vec - 乘数
     * @return 返回点乘结果
     */
    T operator*(const UTVector2 &vec) const
    {
        return m_tX*vec.m_tX+m_tY*vec.m_tY;
    }
private:
    T m_tX;
    T m_tY;
};

/**
 * @brief 定义常用向量类型
 */
using UTVector2I=UTVector2<int>;
using UTVector2F=UTVector2<float>;
using UTVector2D=UTVector2<double>;

END_SPACE_LANGE_VDR

#endif // UT_VECTOR_2_H